package com.goudan.ojcloudjudgeservice.codesandbox.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.goudan.ojcloudjudgeservice.codesandbox.CodeSandBox;
import com.goudan.ojmodel.codesandbox.ExecuteCodeRequest;
import com.goudan.ojmodel.codesandbox.ExecuteCodeResponse;
import com.goudan.ojmodel.codesandbox.JudgeInfo;

import java.util.Arrays;
import java.util.Collections;

/**
 * AI代码沙箱：调用阿里云 DashScope 模型模拟代码执行
 */
public class ThirdPartyCodeSandbox implements CodeSandBox {

    private static final String API_KEY = "sk-71b374611f8a46319dc0f5252fad46ab"; // 请替换成你自己的真实 key

    @Override
    public ExecuteCodeResponse executeCode(ExecuteCodeRequest executeCodeRequest) {
        long startTime = System.currentTimeMillis();

        try {
            String prompt = buildPromptFromRequest(executeCodeRequest);

            Message systemMsg = Message.builder()
                    .role(Role.SYSTEM.getValue())
                    .content(systemPrompt())
                    .build();

            Message userMsg = Message.builder()
                    .role(Role.USER.getValue())
                    .content(prompt)
                    .build();

            GenerationParam param = GenerationParam.builder()
                    .apiKey(API_KEY)
                    .model("qwen3-coder-plus")
                    .messages(Arrays.asList(systemMsg, userMsg))
                    .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                    .build();

            GenerationResult result = new Generation().call(param);
            String content = result.getOutput().getChoices().get(0).getMessage().getContent();

            String json = extractJson(content);
            ObjectMapper objectMapper = new ObjectMapper();
            ExecuteCodeResponse response = objectMapper.readValue(json, ExecuteCodeResponse.class);
            return response;

        } catch (ApiException | NoApiKeyException | InputRequiredException e) {
            return buildErrorResponse("调用 AI 接口失败: " + e.getMessage());
        } catch (Exception e) {
            return buildErrorResponse("AI 返回结果解析失败: " + e.getMessage());
        }
    }

    private String systemPrompt (){
        return"你是一个代码执行沙箱，负责模拟代码运行并返回 JSON 格式的结果。\n" +
                "\n" +
                "返回的 JSON 格式如下：\n" +
                "{\n" +
                "\"outputList\": \\[\"输出按行分割\"],\n" +
                "\"message\": \"运行成功或失败信息\",\n" +
                "\"status\": 2 或 3,\n" +
                "\"judgeInfo\": {\n" +
                "\"message\": \"判题状态消息，必须严格为以下之一的中文描述：成功、答案错误、编译错误、内存溢出、超时、展示错误、等待中、输出溢出、危险操作、运行错误、系统错误\",\n" +
                "\"memory\": 整数（KB），\n" +
                "\"time\": 整数（ms）\n" +
                "}\n" +
                "}\n" +
                "\n" +
                "请严格只输出模拟运行后的 JSON 内容，不要输出任何多余文字。\n";
    }
    /**
     * 构造 AI 提示词
     */
    private String buildPromptFromRequest(ExecuteCodeRequest req) throws Exception {
        return "请模拟运行以下代码，并返回 JSON 格式的结果：\n" +
                JSONUtil.toJsonStr(req);
    }

    /**
     * 从 AI 返回内容中提取 JSON 部分
     */
    private String extractJson(String content) {
        int start = content.indexOf("{");
        int end = content.lastIndexOf("}");
        if (start != -1 && end != -1 && end > start) {
            return content.substring(start, end + 1);
        }
        return "{}";
    }

    /**
     * 构造错误响应
     */
    private ExecuteCodeResponse buildErrorResponse(String message) {
        ExecuteCodeResponse response = new ExecuteCodeResponse();
        response.setOutputList(Collections.emptyList());
        response.setMessage(message);
        response.setStatus(1);
        JudgeInfo judgeInfo = new JudgeInfo();
        judgeInfo.setMessage("运行失败");
        judgeInfo.setMemory(0L);
        judgeInfo.setTime(0L);
        response.setJudgeInfo(judgeInfo);

        return response;
    }
}


